package wrapper

import (
	"context"
	"github.com/micro/go-micro/v2/client"
	"github.com/micro/go-micro/v2/server"
	"github.com/opentracing/opentracing-go"
	log "github.com/sirupsen/logrus"
	"micro.area.server/plugins"
	"time"
)

type ClientWrapper struct {
	client.Client
}

func (c *ClientWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
	log.Printf("[wrapper] client request to service: %s endpoint: %s", req.Service(), req.Endpoint())
	return c.Client.Call(ctx, req, rsp, opts...)
}

func NewClientWrapper(c client.Client) client.Client {
	return &ClientWrapper{c}
}

func WrapperLogg(next server.HandlerFunc) server.HandlerFunc {
	return func(ctx context.Context, req server.Request, rsp interface{}) error {
		start := time.Now()
		log.Info("WrapperLogg start time:%+v", start)
		err := next(ctx, req, rsp)
		defer log.Info("WrapperLogg end time:%+v", time.Now().Sub(start))
		return err
	}
}

func WrapperLoggers() server.HandlerWrapper {
	return func(next server.HandlerFunc) server.HandlerFunc {
		return func(ctx context.Context, req server.Request, rsp interface{}) error {
			start := time.Now()
			log.Info("start time:%+v", start)
			err := next(ctx, req, rsp)
			defer log.Info("end time:%+v", time.Now().Sub(start))
			return err
		}
	}
}

func WrapperTracer() server.HandlerWrapper {
	return func(next server.HandlerFunc) server.HandlerFunc {
		return func(ctx context.Context, req server.Request, rsp interface{}) error {
			tracer, closer, err := plugins.NewJaegerTracer(req.Service(), "127.0.0.1:6831")
			if err != nil {
				return err
			}
			defer closer.Close()
			opentracing.SetGlobalTracer(tracer)
			span, md, spanCtx := plugins.TracerContext(ctx, req.Endpoint())
			err = next(spanCtx, req, rsp)
			defer plugins.TracerFinish(span, req.Service()+req.Endpoint(), md, req, rsp)
			return err
		}
	}
}

func WrapperLog() server.HandlerWrapper {
	return func(next server.HandlerFunc) server.HandlerFunc {
		return func(ctx context.Context, req server.Request, rsp interface{}) error {
			start := time.Now()
			log.Info("start time:%+v", start)
			err := next(ctx, req, rsp)
			defer log.Info("end time:%+v", time.Now().Sub(start))
			return err
		}
	}
}
